﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LingDong.ConfigProvider;
using LingDong.IndexEntities.Dictionary;
using LingDong.IndexEntities.Document;
using PanGu;

namespace LingDong.QueryCore
{
    internal class AbstractExtractor
    {
        internal static string GetAbstract(ParsedDocumentEntity doc,
                                            List<Dictionary<int, InvertedListEntity>> allInvertedListDic,
                                            List<string> query)
        {
            // find top sencentens
            Dictionary<int, int> senIndexOccerrenceNumberDic = new Dictionary<int, int>();
            Dictionary<int, List<int>> senIndexTermIndexDic = new Dictionary<int, List<int>>();
            int count = allInvertedListDic.Count;
            for (int i = 0; i < count; i++)
            {
                List<HitListEntity> hitList = allInvertedListDic[i][doc.DocID].HitList;
                foreach (HitListEntity entity in hitList)
                {
                    AddToDictionary(senIndexOccerrenceNumberDic, entity.SentenceIndex);
                    AddToDictionary(senIndexTermIndexDic, entity.SentenceIndex, entity.TermIndex);
                }
            }

            List<int> senIndexList = senIndexOccerrenceNumberDic.Keys.OrderByDescending(k => senIndexOccerrenceNumberDic[k]).ToList();
            int abstractSenNumber = Math.Min(maxSentenceNumber, senIndexList.Count);

            StringBuilder result = new StringBuilder();
            for (int i = 0; i < abstractSenNumber; i++)
            {
                string sentence = doc.SentenceList[senIndexList[i]];
                List<string> termList = new Segment().DoSegment(sentence).Select<WordInfo, string>(w => w.Word).ToList<string>();

                int minIndex = senIndexTermIndexDic[senIndexList[i]].Min();
                int startIndex = Math.Max(0, minIndex - maxSentenceLength / 2);
                int len = Math.Min(maxSentenceLength, termList.Count - startIndex);

                for (int j = 0; j < len; j++)
                {
                    result.Append(termList[startIndex + j]);
                }

                if (i < abstractSenNumber - 1)
                {
                    result.Append(sentenceSplitter);
                }
            }

            return HightLight(result, query);
        }

        private static string HightLight(StringBuilder result, List<string> query)
        {
            foreach (string word in query)
            {
                string highLighted = hightLightPrefix + word + hightLightPostfix;
                result = result.Replace(word, highLighted);
            }
            return result.ToString();
        }

        private static void AddToDictionary(Dictionary<int, List<int>> dictionary, int senIndex, short termIndex)
        {
            if (!dictionary.ContainsKey(senIndex))
            {
                dictionary[senIndex] = new List<int>();
            }
            dictionary[senIndex].Add(termIndex);
        }

        private static void AddToDictionary(Dictionary<int, int> dictionary, int senIndex)
        {
            if (dictionary.ContainsKey(senIndex))
            {
                dictionary[senIndex]++;
            }
            else
            {
                dictionary[senIndex] = 1;
            }
        }

        private static int maxSentenceLength = ConfigQuery.Default.AbstractMaxSentenceLength;
        private static int maxSentenceNumber = ConfigQuery.Default.AbstractMaxSentenceNumber;
        private static string sentenceSplitter = ConfigQuery.Default.AbstractSentenceSplitter;
        private static string hightLightPrefix = ConfigQuery.Default.AbstractHighLightPrefix;
        private static string hightLightPostfix = ConfigQuery.Default.AbstractHighLightPostfix;
    }
}
